ピクセルシェーダがMip mapで適切なサイズの画像を選択する仕組み
https://www.youtube.com/watch?v=-Ki1Q2CAqEc
一般論
普通に縮小すると情報が落ちる
時間をかけると綺麗に縮小できる
https://gyazo.com/aa8c4c5f136020472328f678ba6a9bd6
このような綺麗な縮小をシェーダーですることができない
テクスチャのピクセルをtex2Dでひろうとき
tex2D(_MainTex, i.uv)
ピクセルシェーダでフラグメントシェーダで隣のUVの座標が大きくジャンプしていたらどうしても荒くなる
i.uvが大きくなる
https://gyazo.com/2910f7bf0cec3f2dd1229f665e4d07cc
無限平面を作ることを考える
カメラの視界に必ず入るような平面を頂点シェーダで計算したい
頂点を広げる
https://gyazo.com/445059c20821ce66409622791e9da6de
テクスチャ画像のuvにはワールド座標をそのまま入れる
すると繰り返される
テクスチャ画像は[0, 1]平面で構成される
1を超えたら繰り返す(ようにできる)。折り返しを返すようになっている(repeat)
Clampならまた別になる
https://gyazo.com/426432d5d22ae566fc57eb2e42ddab8a
無限平面の端っこはなぜ綺麗に縮小されるのか?
https://gyazo.com/38499a634a1ee291ccbf34ebe39fc8f9
テクスチャがインポートされたら、半分のサイズのテクスチャをあらかじめ作る
縮小すみのテクスチャが使用される
ピクセルシェーダシェーダはtex2Dをよんでいるだけなのに、mip mapのレベルをどう選択するのか?
ピクセルシェーダは必ず4ピクセル同時に実行しているので、tex2Dを計算するときに異なる4つのuvを取得できる
なのでif文をかくと隣接する方は別の分岐にしているかもしれない
「おそらく両方実行して、どちらかを選択するコードが出ている」
隣接ピクセルのuvの値との差分が取れるので、飛び具合がわかり、適切なmip mapを取れる
カメラ近くだと隣接するUVがあまり飛ばないが(テクスチャがあまり変わらない)、遠くだとかなり変わる、みたいなのを見ている??
まずUVがずれるというものがなんなのか確認したい
テクスチャ上のローカル座標だと思っている
隣接ピクセルのUVの差分は
自分に適用されるUV(0,0.1)
隣接ピクセル(1,0.2)
の差分のことだ思う
カメラから遠くなると、隣接ピクセルのUVの距離が遠くなるはず
これを見てどうにかしている(どうやってどうにかしてるのかは謎)、のだと思っている
繰り返しが気になるので対応する
単位範囲ごとにuvをずらす
https://gyazo.com/1a8b320a909797b4dd271567e89f8d61
繰り返しは気にならなくなったが、mip mapがちらついてしまう
正しいmip mapが引けていないのが原因
なぜ?
tex2Dという関数は、ハードウェアにより巧妙に作られていて、同時に実行される隣接ピクセルの処理と組み合わせて動作します。ここに渡されるuvが連続していることが前提になっていて、隣接ピクセルとの微分値でmipmapが選択されるのです。
どうすればいいか?
tex2Dではなくtex2Dgradを使う
ddx, ddyで横/縦のピクセルとのUVの変化量を取ることができる
gradはuvが連続していなくても大丈夫なようだけどその説明はない基素.icon
勾配な急なところはuvのエッジだということはわかる
これでuvが日連続でもわかるようになっている?
変化量を取るとエッジ抽出ができる